home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / dev / misc / FetchRefs1.3.lha / FetchRefs1.3 / Source.lha / Source / FetchRefs / FindRef.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-07-04  |  17.5 KB  |  673 lines

  1. /* FindRef.c
  2. Originaly written by Anders Melchiorsen, modified by Roland Florac (SAS/C compiler) */
  3.  
  4. #include "FetchRefs.h"
  5.  
  6. static LONG __regargs BuildRefList (struct FindRefOptions *args);
  7. static void __regargs FindRefInteractive (struct FindRefOptions *args, struct FindRefReturnStruct *ret);
  8. static void __regargs PutRef (struct ListViewNode *item, STRPTR destfile, struct FindRefReturnStruct *ret);
  9. static void SwitchToFileIndex (void);
  10. static struct Screen * __regargs FindScreen (STRPTR pubname);
  11.  
  12. extern struct IntuitionBase * IntuitionBase;
  13.  
  14. APTR ListPool;
  15. static struct List RefsFound;
  16. static struct TR_Project *RefListPrj;
  17.  
  18. struct ListViewNode {
  19.  
  20. /* ln_name in the Node points to the string that is to be shown in the
  21.  * listview. ln_type is 1 for file references, 2 for normal ones.
  22.  *
  23.  * fileentry is a pointer to the FileEntry in which the reference is
  24.  *
  25.  * refsentry is a pointer to the reference to fetch.
  26.  *
  27.  * ListViewText is used if we build a new string for the listview.
  28.  */
  29.  
  30.     struct Node node;
  31.     struct FileEntry *fileentry;
  32.     struct RefsEntry *refsentry;
  33.     UBYTE ListViewText[0];
  34. };
  35.  
  36. /* Triton specifications */
  37. enum {    ID_LIST_WINDOW = 1,
  38.     ID_LIST_LIST, ID_LIST_PATTERN, ID_LIST_OK, ID_LIST_FILE, ID_LIST_CANCEL
  39.      };
  40.  
  41. struct TagItem RefListOutline[] =
  42. {
  43.     WindowID (ID_LIST_WINDOW),
  44.     WindowTitle (0),
  45.     ScreenTitle (0),
  46.     WindowBackfillWin,
  47.     WindowPosition (TRWP_CENTERDISPLAY),
  48.     WindowFlags (TRWF_HELP|TRWF_NOZIPGADGET|TRWF_NOESCCLOSE),
  49.     TRWI_PubScreen, NULL,         /* Filled in on the fly */
  50.  
  51.     HorizGroupA,
  52.     Space,
  53.  
  54.     VertGroupA,
  55.         Space,
  56.  
  57.         HorizGroupA,
  58.         ListSS (&RefsFound, ID_LIST_LIST, 0, 0),
  59.             TRAT_MinWidth,  60,
  60.             TRAT_MinHeight, 15,
  61.         EndGroup,
  62.  
  63.         Space,
  64.  
  65.         HorizGroupC,
  66.         TextN (0),
  67.             TRAT_ID, ID_LIST_PATTERN,
  68.         Space,
  69.         StringGadget ("", ID_LIST_PATTERN),
  70.             TRAT_Flags, TRST_NORETURNBROADCAST,
  71.         EndGroup,
  72.  
  73.         Space,
  74.  
  75.         HorizGroupE,
  76.         ButtonR (0, ID_LIST_OK),
  77.         Space,
  78.         Button (0, ID_LIST_FILE),
  79.         Space,
  80.         ButtonE (0, ID_LIST_CANCEL),
  81.         EndGroup,
  82.  
  83.         Space,
  84.     EndGroup,
  85.  
  86.     Space,
  87.     EndGroup,
  88. EndProject
  89. };
  90.  
  91. /* FindRef() - interface to fetch a reference to file
  92.  * Actual look-up routine. Copies the reference to 'ref' into a file */
  93. void __regargs FindRef (struct FindRefOptions *args, struct FindRefReturnStruct *ret)
  94. {
  95.     LONG refsfound = 0;
  96.     UBYTE pattern[128];
  97.  
  98.     /* Assume failure until proven wrong */
  99.     ret->Result = RET_FAULT;
  100.     ret->Number = ERROR_NO_FREE_STORE;
  101.  
  102.     if (! NewMatchList())
  103.     goto error;
  104.     /* Build a list of references matching the requested one */
  105.  
  106.     /* If the search  pattern  turns out to be blank we show
  107.      * the "references found" window anyway -- to allow the
  108.      * user to enter a new one. */
  109.  
  110.     if (ParsePatternNoCase (args->Reference, pattern, 128) != -1)
  111.     if (MatchPatternNoCase (pattern, ""))
  112.         refsfound = 2;
  113.  
  114.     if (!refsfound)
  115.     {
  116.     refsfound = BuildRefList (args);
  117.  
  118.     if (refsfound > 0)
  119.     {
  120.         ret->Result = refsfound;
  121.         goto error;
  122.     }
  123.     else
  124.         refsfound = -refsfound;
  125.     }
  126.  
  127.     /* If exactly one match was found we simply fetch it. Otherwise we
  128.      * ask the user for further help.
  129.      */
  130.     if (refsfound == 1)
  131.     PutRef ((struct ListViewNode *) RefsFound.lh_Head, args->DestFile, ret);
  132.     else if (refsfound > 1)
  133.     FindRefInteractive (args, ret);
  134.     else
  135.     ret->Result = RET_NO_MATCH;
  136.  
  137. error:
  138.  
  139.     /* Free the list */
  140.     LibDeletePool (ListPool);
  141.     ListPool = NULL;
  142. }
  143.  
  144. /* FindRefInteractive() - open window and ask which reference to use */
  145. static void __regargs FindRefInteractive (struct FindRefOptions *args, struct FindRefReturnStruct *ret)
  146. {
  147.     struct Screen *scr;
  148.     BOOL swappedscreen = FALSE;
  149.  
  150.     /* Get a pointer to the Screen to open on. The screen is
  151.      * LockPubScreen()'ed and we must unlock (is done further down).
  152.      */
  153.     if (!(scr = FindScreen (args->PubScreen)))
  154.     return;
  155.  
  156.     /* Bring the screen to the front if it is not already there */
  157.     if (IntuitionBase->FirstScreen != scr)
  158.     {    ScreenToFront (scr);
  159.     swappedscreen = TRUE;
  160.     }
  161.  
  162.     /* Fill in the variable value of the TagList */
  163.     {
  164.     ULONG *t = (ULONG *) RefListOutline;
  165.  
  166.     while (*t++ != TRWI_PubScreen) ;
  167.     *t = (ULONG)scr;
  168.     }
  169.  
  170.     /* Open and handle everything */
  171.     RefListOutline[1].ti_Data = (ULONG) GetString (TEXTE_REFERENCE);
  172.     RefListOutline[2].ti_Data = (ULONG) GetString (TEXTE_VERSION);
  173.     RefListOutline[23].ti_Data = (ULONG) GetString (TEXTE_FIND_PATTERN);
  174.     RefListOutline[33].ti_Data = (ULONG) GetString (TEXTE_FETCHREF);
  175.     RefListOutline[38].ti_Data = (ULONG) GetString (TEXTE_LISTE);
  176.     RefListOutline[42].ti_Data = (ULONG) GetString (TEXTE_CANCEL);
  177.     if (RefListPrj = TR_OpenProject (Application, RefListOutline))
  178.     {
  179.     struct TR_Message *msg;
  180.  
  181.     if (IsListEmpty (&RefsFound))
  182.     {
  183.         /* Disable fetch gadgets if the references window is empty */
  184.         TR_SetAttribute (RefListPrj, ID_LIST_FILE, TRAT_Disabled, TRUE);
  185.         TR_SetAttribute (RefListPrj, ID_LIST_OK, TRAT_Disabled, TRUE);
  186.         TR_SendMessage (RefListPrj, ID_LIST_PATTERN, TROM_ACTIVATE, NULL);
  187.     }
  188.     else
  189.     {
  190.         /* Copy the search pattern into the string gadget buffer */
  191.         TR_SetAttribute (RefListPrj, ID_LIST_PATTERN, NULL, (ULONG)args->Reference);
  192.     }
  193.  
  194.     /* Use the string gadget as pattern buffer from now on */
  195.     args->Reference = (STRPTR) TR_GetAttribute (RefListPrj, ID_LIST_PATTERN, NULL);
  196.  
  197.     ret->Result = RET_NO_MATCH;
  198.     while (ret->Result == RET_NO_MATCH)
  199.     {
  200.         TR_Wait (Application, NULL);
  201.  
  202.         while (msg = TR_GetMsg (Application))
  203.         {
  204.         if (msg->trm_Class == TRMS_HELP)
  205.             GiveHelp (scr);
  206.         else if (msg->trm_Class == TRMS_CLOSEWINDOW)
  207.             ret->Result = RET_ABORT;
  208.         else
  209.         {
  210.             switch (msg->trm_ID)
  211.             {
  212.             /* Listview; if double click we fall through to
  213.              * the "Fetch reference" gadget, ID_LIST_OK. */
  214.             case ID_LIST_LIST:
  215.                 if (!(msg->trm_Qualifier & IEQUALIFIER_REPEAT))
  216.                 break;
  217.  
  218.             /* "Fetch reference" gadget */
  219.             case ID_LIST_OK:
  220.             {
  221.                 struct ListViewNode *f;
  222.  
  223.                 TR_LockProject (RefListPrj);
  224.  
  225.                 /* Find the selected node and fetch it */
  226.                 f = ListOffsetToPtr (&RefsFound, TR_GetAttribute(RefListPrj, ID_LIST_LIST, TRAT_Value));
  227.                 PutRef (f, args->DestFile, ret);
  228.  
  229.                 TR_UnlockProject (RefListPrj);
  230.             }
  231.             break;
  232.  
  233.             /* Build a new list based on the new search pattern */
  234.             case ID_LIST_PATTERN:
  235.                 TR_LockProject (RefListPrj);
  236.  
  237.                 if (BuildRefList (args) == 0)
  238.                 {
  239.                 /* Disable fetch and 'list file' gadget if no references are
  240.                  * found.
  241.                  */
  242.                 TR_SetAttribute (RefListPrj, ID_LIST_FILE, TRAT_Disabled, TRUE);
  243.                 TR_SetAttribute (RefListPrj, ID_LIST_OK, TRAT_Disabled, TRUE);
  244.                 }
  245.                 else
  246.                 {
  247.                 /* As we get a new list we can once again do ID_LIST_FILE
  248.                  * and fetch a reference
  249.                  */
  250.                 TR_SetAttribute (RefListPrj, ID_LIST_FILE, TRAT_Disabled, FALSE);
  251.                 TR_SetAttribute (RefListPrj, ID_LIST_OK, TRAT_Disabled, FALSE);
  252.                 }
  253.  
  254.                 /* Now actually display the new list */
  255.                 TR_SetAttribute (RefListPrj, ID_LIST_LIST, NULL, (ULONG)&RefsFound);
  256.  
  257.                 /* And finally re-activate the GUI */
  258.                 TR_UnlockProject (RefListPrj);
  259.             break;
  260.  
  261.             /* Switch reference list to the file of
  262.              * the selected reference.
  263.              */
  264.             case ID_LIST_FILE:
  265.                 SwitchToFileIndex();
  266.             break;
  267.  
  268.             /* Cancel */
  269.             case ID_LIST_CANCEL:
  270.                 ret->Result = RET_ABORT;
  271.             break;
  272.             }
  273.         }
  274.  
  275.         TR_ReplyMsg (msg);
  276.         }
  277.     }
  278.  
  279.     TR_CloseProject (RefListPrj);
  280.     RefListPrj = NULL;
  281.     }
  282.  
  283.     if (swappedscreen)
  284.     ScreenToBack (scr);
  285.     UnlockPubScreen (NULL, scr);
  286. }
  287.  
  288. /* GiveHelp() - open guide positioned at the help for <id> */
  289. void __regargs GiveHelp (struct Screen *scr)
  290. {
  291.     struct Library *AmigaGuideBase;
  292.     struct NewAmigaGuide nag = { NULL };
  293.     AMIGAGUIDECONTEXT handle;
  294.  
  295.     nag.nag_Name = "FetchRefs_FR.guide";
  296.     nag.nag_Screen = scr;
  297.     nag.nag_Node = "4.";
  298.  
  299.     /* Show the guide */
  300.     if (AmigaGuideBase = OpenLibrary ("amigaguide.library", 34))
  301.     {
  302.     if (handle = OpenAmigaGuideA (&nag, NULL))
  303.         CloseAmigaGuide (handle);
  304.     else
  305.         PostMessage (GetString (TEXTE_GUIDE));
  306.  
  307.     CloseLibrary (AmigaGuideBase);
  308.     }
  309.     else
  310.     PostMessage (GetString (TEXTE_AMIGAGUIDE));
  311. }
  312.  
  313. /* NewMatchList() - free the list (if any) of matches and allocate new one */
  314. APTR NewMatchList (void)
  315. {
  316.     /* Empty the list and create a new, empty one. Empty the listview, too */
  317.     if (RefListPrj)
  318.     TR_SetAttribute (RefListPrj, ID_LIST_LIST, NULL, (ULONG)~0);
  319.  
  320.     NewList (&RefsFound);
  321.  
  322.     if (RefListPrj)
  323.     {
  324.     TR_SetAttribute (RefListPrj, ID_LIST_LIST, NULL, (ULONG)&RefsFound);
  325.     TR_SetAttribute (RefListPrj, ID_LIST_LIST, NULL, (ULONG)~0);
  326.     }
  327.  
  328.     LibDeletePool (ListPool);
  329.     return (ListPool = LibCreatePool (NULL, 8192, 8192));
  330. }
  331.  
  332. /* PutRef() - writes a reference to file */
  333. /* Write the reference. Handles the writing both to a normal file and to the
  334.  * clipboard (through iffparse.library). */
  335. #define ID_FTXT MAKE_ID('F','T','X','T')
  336. #define ID_CHRS MAKE_ID('C','H','R','S')
  337. static void __regargs PutRef (struct ListViewNode *item, STRPTR destfile, struct FindRefReturnStruct *ret)
  338. {
  339.     BPTR from;
  340.     STRPTR buf = NULL;
  341.     LONG fetchfrom, fetchlength;
  342.  
  343.     /* Figure out the actual file length if the reference is a complete file.
  344.      * Otherwise just grab the reference size from the list.
  345.      */
  346.     fetchfrom = 0;
  347.     fetchlength = -1;
  348.     if (item->node.ln_Type == 2)
  349.     {
  350.     fetchfrom = item->refsentry->Offset;
  351.     fetchlength = item->refsentry->Length;
  352.     }
  353.     if (fetchlength == -1)
  354.     fetchlength = FileLength (item->fileentry->Name);
  355.  
  356.     /* Attempt to open file, allocate memory, and read reference */
  357.     if (from = Open (item->fileentry->Name, MODE_OLDFILE))
  358.     {
  359.     if (buf = LibAllocPooled (ListPool, fetchlength))
  360.     {
  361.         Seek (from, fetchfrom, OFFSET_BEGINNING);
  362.         Read (from, buf, fetchlength);
  363.     }
  364.  
  365.     Close (from);
  366.     }
  367.     else
  368.     ret->Number = IoErr();
  369.  
  370.     /* Now write the reference */
  371.     if (buf)
  372.     {
  373.     /* Write to a normal file if destination is not "CLIP#?" */
  374.     if (strncmp (destfile, "CLIP", 4) != 0)
  375.     {
  376.         BPTR to;
  377.  
  378.         if (to = Open (destfile, MODE_NEWFILE))
  379.         {
  380.         if (Write (to, buf, fetchlength) == fetchlength)
  381.             ret->Result = RET_MATCH;
  382.         else
  383.             ret->Number = IoErr();
  384.  
  385.         Close (to);
  386.         } else
  387.         ret->Number = IoErr();
  388.  
  389.     }
  390.     else  /* Write to a clipboard unit */
  391.     {
  392.         struct Library *IFFParseBase;
  393.         if (IFFParseBase = OpenLibrary ("iffparse.library", 37))
  394.         {
  395.         struct IFFHandle *iff;
  396.  
  397.         if (iff = AllocIFF())
  398.         {
  399.             if (iff->iff_Stream = (unsigned long) OpenClipboard (atoi(&(destfile[4]))))
  400.             {
  401.             InitIFFasClip(iff);
  402.             if (OpenIFF(iff, IFFF_WRITE) == 0)
  403.             {
  404.                 if (PushChunk (iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN) == 0)
  405.                 {
  406.                 if (PushChunk (iff, 0, ID_CHRS, fetchlength) == 0)
  407.                 {
  408.                     if (WriteChunkBytes (iff, buf, fetchlength) == fetchlength)
  409.                     {
  410.                     if (PopChunk (iff) == 0)
  411.                         ret->Result = RET_MATCH;
  412.                     }
  413.                     PopChunk (iff);
  414.                 }
  415.                 }
  416.                 CloseIFF (iff);
  417.             }
  418.             CloseClipboard ((struct ClipboardHandle *)iff->iff_Stream);
  419.             }
  420.             FreeIFF (iff);
  421.         }
  422.         CloseLibrary (IFFParseBase);
  423.         }
  424.     }
  425.     }
  426.  
  427.     /* If we wrote the reference we can return what line number to jump to.
  428.      * For a file reference this is zero.
  429.      */
  430.     if (ret->Result == RET_MATCH)
  431.     ret->Number = (item->node.ln_Type == 1) ? 0 : item->refsentry->Goto;
  432. }
  433.  
  434. /* BuildRefList() - builds a list of all the matching references */
  435. /* This is a call back function for the sort routine.. */
  436. BOOL __regargs SortListFunct (struct ListViewNode *a, struct ListViewNode *b, ULONG data)
  437. {   BOOL r;
  438.     /* Sort alphabetically */
  439.     if (a->node.ln_Type == b->node.ln_Type)
  440.     {    r = ( stricmp (a->node.ln_Name, b->node.ln_Name) > 0 );
  441.     return r;
  442.     }
  443.  
  444.     /* Put files at the top */
  445.     r = (a->node.ln_Type == 2);
  446.     return r;
  447. }
  448.  
  449. static LONG __regargs BuildRefList (struct FindRefOptions *args)
  450. {
  451.     STRPTR pattern;
  452.     LONG numofrefs = 0, len, res;
  453.     struct RefsEntry *currref;
  454.     struct FileEntry *currfile;
  455.  
  456.     /* First of all: Initialize the list of matching references */
  457.     if (! NewMatchList())
  458.     return ERROR_NO_FREE_STORE;
  459.  
  460.     /* Tokenize pattern string */
  461.     len = strlen (args->Reference) * 2 + 2;
  462.  
  463.     /* We just return as fail code is already set above */
  464.     if (! (pattern = LibAllocPooled (ListPool, len)))
  465.     return ERROR_NO_FREE_STORE;
  466.  
  467.     /* Tokenize the search string */
  468.     if (args->Case)
  469.     res = ParsePattern (args->Reference, pattern, len);
  470.     else
  471.     res = ParsePatternNoCase (args->Reference, pattern, len);
  472.  
  473.     if (res == -1)
  474.     return ERROR_TOO_MANY_LEVELS;
  475.  
  476.     /* Pick up all references */
  477.     for (currfile = (struct FileEntry *) FileList.lh_Head;
  478.         currfile->node.ln_Succ;
  479.         currfile = (struct FileEntry *) currfile->node.ln_Succ)
  480.     {
  481.     /* Check for a match on the file name */
  482.     if (args->FileRef)
  483.     {
  484.         UBYTE name[108], *cutptr;
  485.         /* Isolate the base name (eg. 'INCLUDE:libraries/dos.h' -> 'dos') */
  486.         strcpy (name, FilePart (currfile->Name));
  487.         cutptr = name;
  488.         while (*cutptr)
  489.         {
  490.         if ((*cutptr >= 'a' && *cutptr <= 'z') ||
  491.             (*cutptr >= 'A' && *cutptr <= 'Z') ||
  492.             (*cutptr >= '0' && *cutptr <= '9') ||
  493.             (*cutptr == '_'))
  494.             cutptr++;
  495.         else
  496.             *cutptr = 0;
  497.         }
  498.  
  499.         /* Create an item to add to the RefsFound list */
  500.         if ((args->Case) ? MatchPattern(pattern, name) : MatchPatternNoCase(pattern, name))
  501.         {
  502.         struct ListViewNode *r;
  503.  
  504.         if (r = LibAllocPooled (ListPool, sizeof(struct ListViewNode)))
  505.         {
  506.             r->fileentry = currfile;
  507.             r->node.ln_Type = 1;
  508.             r->node.ln_Name = currfile->Name;
  509.  
  510.             AddTail (&RefsFound, &r->node);
  511.             numofrefs++;
  512.         }
  513.         }
  514.     }
  515.  
  516.     /* Check all the RefsEntry's in this FileEntry for a match */
  517.     for (currref = (struct RefsEntry *) currfile->RefsList.lh_Head;
  518.         currref->node.ln_Succ;
  519.         currref = (struct RefsEntry *) currref->node.ln_Succ)
  520.     {
  521.         if ((args->Case) ? MatchPattern(pattern, currref->Name) : MatchPatternNoCase(pattern, currref->Name))
  522.         {
  523.         struct ListViewNode *r;
  524.         if (r = LibAllocPooled (ListPool, sizeof(struct ListViewNode) + strlen(currfile->Name) + strlen(currref->Name) + 5))
  525.         {
  526.             r->fileentry = currfile;
  527.             r->refsentry = currref;
  528.             r->node.ln_Type = 2;
  529.             r->node.ln_Name = r->ListViewText;
  530.  
  531.             SPrintf (r->ListViewText, "%s in %s", currref->Name, currfile->Name);
  532.             /* strcpy (r->ListViewText, currref->Name);
  533.             strcat (r->ListViewText, " in ");
  534.             strcat (r->ListViewText, currfile->Name); */
  535.  
  536.             AddTail (&RefsFound, &r->node);
  537.             numofrefs++;
  538.         }
  539.         }
  540.     }
  541.     }
  542.     SortExecList (&RefsFound, SortListFunct, 0);
  543.  
  544.     /* Negate the number of matches; positive return code means failure */
  545.     return -numofrefs;
  546. }
  547.  
  548. static void SwitchToFileIndex (void)
  549. {
  550.     struct FileEntry *file;
  551.     struct RefsEntry *selectedref, *ref;
  552.     struct ListViewNode *selected;
  553.     LONG selectedpos = 0;
  554.  
  555.     TR_LockProject (RefListPrj);
  556.     TR_SetAttribute (RefListPrj, ID_LIST_FILE, TRAT_Disabled, TRUE);
  557.  
  558.     selected = ListOffsetToPtr (&RefsFound, TR_GetAttribute(RefListPrj, ID_LIST_LIST, TRAT_Value));
  559.     file = selected->fileentry;
  560.     selectedref = selected->refsentry;
  561.  
  562.     if (!NewMatchList())
  563.     goto nomem;
  564.  
  565.     /* Build a new list */
  566.     for (ref = (struct RefsEntry *) file->RefsList.lh_Head;
  567.         ref->node.ln_Succ;
  568.         ref = (struct RefsEntry *) ref->node.ln_Succ)
  569.     {
  570.     struct ListViewNode *r;
  571.  
  572.     if (r = LibAllocPooled (ListPool, sizeof(struct ListViewNode) + strlen(ref->Name) + 4 + strlen(file->Name) + 1))
  573.     {
  574.         r->fileentry = file;
  575.         r->refsentry = ref;
  576.         r->node.ln_Type = 2;
  577.         r->node.ln_Name = r->ListViewText;
  578.         SPrintf (r->ListViewText, "%s => %s", ref->Name, file->Name);
  579.  
  580.         AddTail (&RefsFound, &r->node);
  581.     }
  582.     }
  583.  
  584.     SortExecList (&RefsFound, SortListFunct, 0);
  585.  
  586.     /* Figure out where the reference we started with has ended in new list */
  587.     for (selected = (struct ListViewNode *) RefsFound.lh_Head;
  588.         selected->node.ln_Succ;
  589.         selected = (struct ListViewNode *) selected->node.ln_Succ)
  590.     {
  591.     if (selected->refsentry == selectedref)
  592.         break;
  593.     selectedpos++;
  594.     }
  595.     if (!selected->node.ln_Succ)
  596.     selectedpos = 0;
  597.  
  598. nomem:
  599.     /* Update GUI */
  600.     TR_SetAttribute (RefListPrj, ID_LIST_LIST, NULL, (ULONG)&RefsFound);
  601.     TR_SetAttribute (RefListPrj, ID_LIST_LIST, TRAT_Value, selectedpos);
  602.     TR_SetAttribute (RefListPrj, ID_LIST_LIST, TRLV_Top, selectedpos);
  603.  
  604.     TR_UnlockProject (RefListPrj);
  605. }
  606.  
  607. /* FindScreen() - return best Screen, based prefered <pubname> PubScr name */
  608. static struct Screen * __regargs FindScreen (STRPTR pubname)
  609. {
  610.     struct Screen *s = NULL;
  611.  
  612.     /* A specific public screen is wanted */
  613.     if (pubname)
  614.     s = LockPubScreen (pubname);
  615.  
  616.     /* Go for the currently active screen */
  617.     if (!s)
  618.     {
  619.     UBYTE wantname[MAXPUBSCREENNAME+1];
  620.     struct Screen *wantscr;
  621.     struct List *publist;
  622.     struct PubScreenNode *pubnode;
  623.  
  624.     publist = LockPubScreenList();
  625.     wantscr = IntuitionBase->ActiveScreen;
  626.     pubnode = (struct PubScreenNode *) publist->lh_Head;
  627.     while (pubnode->psn_Node.ln_Succ)
  628.     {
  629.         if (pubnode->psn_Screen == wantscr)
  630.         strcpy (wantname, pubnode->psn_Node.ln_Name);
  631.         pubnode = (struct PubScreenNode *) pubnode->psn_Node.ln_Succ;
  632.     }
  633.     UnlockPubScreenList();
  634.     s = LockPubScreen (wantname);
  635.     }
  636.  
  637.     /* Last option: default public screen */
  638.     if (!s)
  639.     s = LockPubScreen (NULL);
  640.  
  641.     return s;
  642. }
  643.  
  644. /* FileLength() - returns file length or -1 for failure */
  645. LONG __regargs FileLength (STRPTR name)
  646. {
  647.     BPTR lock;
  648.     __aligned struct FileInfoBlock fib;
  649.  
  650.     if (lock = Lock (name, ACCESS_READ))
  651.     {
  652.     Examine (lock, &fib);
  653.     UnLock (lock);
  654.     return fib.fib_Size;
  655.     }
  656.     else
  657.     return -1;
  658. }
  659.  
  660. void * __regargs ListOffsetToPtr (struct List *l, LONG o)
  661. {
  662.     struct Node *n;
  663.  
  664.     if (o < 0)
  665.     return NULL;
  666.  
  667.     n = l->lh_Head;
  668.     while ((o--) && (n->ln_Succ))
  669.     n = n->ln_Succ;
  670.  
  671.     return (n->ln_Succ) ? n : NULL;
  672. }
  673.